﻿using System;
using System.Common.Native;
using System.Controls.Extensions;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media.Animation;

namespace System.Controls.Windows
{
  public partial class WorkingWindow
  {
    #region ... constructors...

    public WorkingWindow()
    {
      InitializeComponent();
    }

    #endregion

    #region ...public methods...

    public static void Create( string title = "Processing ......" )
    {
      Destroy();

      var window = Application.Current.Windows.OfType<Window>().SingleOrDefault( win => win.IsActive );
      var sd = new ShowData
               {
                 Title = title,
                 Rect = window != null ? window.GetRect() : (Rect?)null
               };


      var thread = new Thread( CreateAndShow );
      thread.SetApartmentState( ApartmentState.STA );
      thread.Start( sd );
    }

    public static void Destroy()
    {
      _semafor.Set();
      _semafor.Reset();
    }

    #endregion

    #region ...private methods...

    private static void CreateAndShow( object par )
    {
      ShowData? sd = null;
      Rect? rect = null;
      var title = string.Empty;

      if ( par != null )
        sd = (ShowData) par;

      if ( sd.HasValue )
      {
        rect = sd.Value.Rect;
        title = sd.Value.Title;
      }

      var window = new WorkingWindow() {Title = title};
      window.Show();

      if ( rect.HasValue )
      {
        var left = rect.Value.Left;
        var top = rect.Value.Top;
        var width = rect.Value.Width;
        var height = rect.Value.Height;

        var this_width = window.Width;
        var this_height = window.Height;

        var this_left = left + ( width - this_width ) / 2;
        var this_top = top + ( height - this_height ) / 2;

        User.MoveWindow( window, (int) this_left, (int) this_top, (int) window.Width, (int) window.Height, true );
      }

      window.ExecuteOpenAnimation();

      do
      {
        window.Dispatcher.ProcessMessages();
      } while ( !_semafor.WaitOne( 10 ) );

      window.ExecuteCloseAnimation();

    }

    private void ExecuteOpenAnimation()
    {
      BeginAnimation( OpacityProperty, GetAnimation( 0, 1 ) );
    }

    private void ExecuteCloseAnimation()
    {
      var dbl_animation = GetAnimation( 1, 0 );
      dbl_animation.Completed += ( sender, args ) => Close();
      BeginAnimation( OpacityProperty, dbl_animation );

      do
      {
        Dispatcher.ProcessMessages();
      } while ( IsVisible );
    }

    private DoubleAnimation GetAnimation( double from, double to )
    {
      return new DoubleAnimation()
             {
               From = from,
               To = to,
               Duration = TimeSpan.FromMilliseconds( 500 ),
               AutoReverse = false
             };
    }


    #endregion

    private static readonly AutoResetEvent _semafor = new AutoResetEvent( false );


    struct ShowData
    {
      public Rect? Rect { get; set; }
      public string Title { get; set; }
    }
  }


}
